/**
  ******************************************************************************
  * @file    sync_method.c
  * @author  ashuai0110
  * @version V2.1
  * @date    2023-09-26
  * @brief   伪线程同步方法(信号量,互斥锁,事件集)
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module.git
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "sync_method.h"

/**
 * @addtogroup modules
 * @{
 */

/**
 * @defgroup sync_method sync_method
 * @{
 */

/* 私有宏定义-----------------------------------------------------------------*/
/**
 * @defgroup sync_method_local_macros sync method local macros
 * @{
 */

/**
 * @defgroup sync_method_check_parameters_validity sync method check parameters validity
 * @{
 */
/* 事件集集合有效性检查 */
#define IS_VALID_EVENT_BITS(x)                                                \
(       (x) != 0u)

/* 事件集标志有效性检查 */
#define IS_VALID_EVENT_FLAG(x)                                                \
(       ((x) == EVENT_OR)                ||                                   \
        ((x) == EVENT_AND))

/* 事件集动作有效性检查 */
#define IS_VALID_EVENT_ACTION(x)                                              \
(       ((x) == EVENT_CLEAR)             ||                                   \
        ((x) == EVENT_HOLD))
/**
 * @}
 */

/**
 * @}
 */

/* 私有类型定义---------------------------------------------------------------*/

/* 私有变量-------------------------------------------------------------------*/

/* 全局变量-------------------------------------------------------------------*/

/* 私有函数原型---------------------------------------------------------------*/

/**
 * @defgroup sync_method_global_functions sync method global functions
 * @{
 */

/**
  * @brief  信号量初始化
  *
  * @param  _sem  : 信号量实例
  *
  * @param  value : 初始值
  *
  * @retval None
  */
void sync_sem_init(sync_sem_t *_sem, uint32_t value)
{
    ASSERT_PARAM(IS_VALID_POINT(_sem));
    
    *_sem = value;
}

/**
  * @brief  释放信号量(信号量+1)
  *
  * @param  _sem : 信号量实例
  *
  * @retval None
  */
void sync_sem_put(sync_sem_t *_sem)
{
    ASSERT_PARAM(IS_VALID_POINT(_sem));
    
    if(0xFFFFFFFFul != *_sem)
    {
        *_sem = *_sem + 1;
    }
}

/**
  * @brief  获取信号量(信号量-1)
  *
  * @param  _sem    : 信号量实例
  *
  * @retval uint8_t
  *    @arg RET_OK  : 获取到信号量
  *    @arg RET_ERR : 无信号量
  */
uint8_t sync_sem_get(sync_sem_t *_sem)
{
    ASSERT_PARAM(IS_VALID_POINT(_sem));
    
    if(0 == *_sem)
    {
        return RET_ERR;
    }

    *_sem = *_sem - 1;
    
    return RET_OK;
}

/**
  * @brief  获取信号量值
  *
  * @param  _sem : 信号量实例
  *
  * @retval 当前信号量值
  */
uint32_t sync_sem_value(sync_sem_t *_sem)
{
    ASSERT_PARAM(IS_VALID_POINT(_sem));
    
    return *_sem;
}


/**
  * @brief  互斥锁初始化
  *
  * @param  _mutex : 互斥锁实例
  *
  * @retval None
  */
void sync_mutex_init(sync_mutex_t *_mutex)
{
    ASSERT_PARAM(IS_VALID_POINT(_mutex));
    
    *_mutex = MUTEX_UNLOCK;
}

/**
  * @brief  互斥锁解锁(释放锁)
  *
  * @param  _mutex : 互斥锁实例
  *
  * @retval None
  */
void sync_mutex_put(sync_mutex_t *_mutex)
{
    ASSERT_PARAM(IS_VALID_POINT(_mutex));
    
    *_mutex = MUTEX_UNLOCK;
}

/**
  * @brief  互斥锁上锁(获得锁)
  *
  * @param  _mutex  : 互斥锁实例
  *
  * @retval uint8_t
  *    @arg RET_OK  : 上锁成功(获得锁)
  *    @arg RET_ERR : 上锁失败(锁被占用)
  */
uint8_t sync_mutex_get(sync_mutex_t *_mutex)
{
    ASSERT_PARAM(IS_VALID_POINT(_mutex));
    
    if(MUTEX_LOCK == *_mutex)
    {
        return RET_ERR;
    }
    
    *_mutex = MUTEX_LOCK;
    
    return RET_OK;
}


/**
  * @brief  事件集初始化
  *
  * @param  _event : 事件集实例
  *
  * @retval None
  */
void sync_event_init(sync_event_t *_event)
{
    ASSERT_PARAM(IS_VALID_POINT(_event));
    
    *_event = 0;
}

/**
  * @brief  设置触发事件
  *
  * @param  _event : 事件集实例
  *
  * @param  bits   : 设置触发的事件集(相关bit置1为设置该事件触发)
  *
  * @retval None
  */
void sync_event_put(sync_event_t *_event, uint32_t bits)
{
    ASSERT_PARAM(IS_VALID_POINT(_event));
    ASSERT_PARAM(IS_VALID_EVENT_BITS(bits));
    
    *_event = *_event | bits;
}

/**
  * @brief  等待事件触发
  *
  * @param  _event      : 事件集实例
  *
  * @param  bits        : 关心的事件集(相应bit置1为关心此事件)
  *
  * @param  eventFlg    : 事件集关心标志 @ref sync_event_flg
  *   @arg  EVENT_OR    : 相应bit任一个为1则认为触发
  *   @arg  EVENT_AND   : 相应bit全部为1则认为触发
  *
  * @param  eventAct    : 事件集触发后动作 @ref sync_event_act
  *   @arg  EVENT_CLEAR : 清除对应事件集合(相应bit置0)
  *   @arg  EVENT_HOLD  : 保持对应事件集合(相应bit不变)
  *
  * @retval uint8_t
  *    @arg RET_OK      : 关心的事件集触发
  *    @arg RET_ERR     : 未触发
  */
uint8_t sync_event_get(sync_event_t *_event, uint32_t bits, uint8_t eventFlg, uint8_t eventAct)
{
    uint8_t ret = RET_ERR;
    
    ASSERT_PARAM(IS_VALID_POINT(_event));
    ASSERT_PARAM(IS_VALID_EVENT_BITS(bits));
    ASSERT_PARAM(IS_VALID_EVENT_FLAG(eventFlg));
    ASSERT_PARAM(IS_VALID_EVENT_ACTION(eventAct));
    
    if(EVENT_OR == eventFlg)
    {
        if((*_event) & bits)
        {
            ret = RET_OK;
        }
    }
    else if(EVENT_AND == eventFlg)
    {
        if(((*_event) & bits) == bits)
        {
            ret = RET_OK;
        }
    }
    
    if(EVENT_CLEAR == eventAct && RET_OK == ret)
    {
        *_event = *_event & (uint32_t)(~bits);
    }
    
    return ret;
}

/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */
